跟一般網頁應用程式一樣,webgis需要前端程式與使用者互動,要開發一個webgis,開發者可以使用各種前端框架。
然而,要炒一盤webgis的菜,就必須要有專屬於gis/地圖的前端框架
這些框架主要功能包含提供地圖,圖層渲染,基本地圖互動、介接資料等功能,Javascript常見的webgis框架包含:
- (1)leaflet
- (2)openlayers
- (3)google maps api
- (4)esri javascript api
一個地圖框架提供我們基本地圖操作,把地圖元素(含空間坐標物件)轉換成前端可操作的元件(DOM等),而為使地圖互動更生動活潑,其它前端工具當然也是可以整合進來的,包含Jquery, Vue, React, Angularjs...甚至D3.js, C3.js等可能都需要整合在webGIS中。
在webGIS應用程式中,可以透過Web service來進行資料操作,這之中最常使用到的是網路圖磚服務(WMTS),例如我們透過 Google maps api 在網頁之中建立一個地圖,這時可以看到Google maps的底圖,這個底圖服務就是透過類似WMTS的概念來實作的。
另一個面向是資料庫,具有空間資料的資料庫稱作「空間資料庫」,空間資料庫能夠執行各種空間查詢,目前包含MSSQL(SQL Spatial)、Postgressql(PostGIS)、 Oracle(Oracel Spatial)、MySQL、MongoDB等各大資料庫系統都有支援空間資料庫的格式及模組。
上面長篇大論講了一堆,本次鐵人賽的目標是把能說清楚這些事情,並加強資料特性的探討,議題逐一擊破。
以下先快速開始一個範例,看一下一個webGIS大致組成:
我們使用leaflet.js new一個地圖並以線上WMTS作為底圖,並把一些資料放上圖台,
這樣其實就是最簡單的一個WebGIS。
引入必要元件
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
<script src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
初始化一個地圖並設定中心經緯度為[25.0375928,121.5529563], 比例尺為10的視角
<div id='map_div' style="height:100%"></div>
var map = L.map('map_div').setView([25.0375928,121.5529563], 10);
一個地圖應用都需要底圖,這邊我們使用官方維護的內政部國土測繪中心wmts
var basemap = L.tileLayer('https://wmts.nlsc.gov.tw/wmts/EMAP/default/GoogleMapsCompatible/{z}/{y}/{x}', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
接下來,webGIS都會有自己的資料,可能是靜態的,也可以是需要資料庫IO的
可能需要從Server side 寫一個api接口取資料
c#:(示意)
//取資料接口..
[Route("api/Poi")]
[httpget]
public JsonResult Poi()
{
//Bson collection example [{"name":"市府店","geo":[25.0375,121.5529]},{"name":"西門店","geo":[25.0401,121.509]}....]
List<PoiDataModel> pois = List<PoiDataModel>();
//取資料...
略..
return Json(...)
}
client side:
接上面的api,把資料放在地圖上
$.ajax({
url: "/api/Poi",
contentType: 'application/json',
type: 'GET',
contentType: 'application/json; charset=utf-8',
success: function(data) {
$.each(data.pois, function(k, v) {
L.marker([v[0], v[1]]).addTo(map)
.bindPopup(v.name)
.openPopup();
});
}
});
另外,可能需要介接其它api資料,我們的範例資料是一個展店的計畫,
在此,我們有需求是看看周圍的商家資料。
這邊我們介接經濟部開放資料說明: A-3 鄰近商家查詢:透過坐標參數,查詢所在位置鄰近商家清冊資料。
接到的資料是geojson,把它們放到地圖上
並以不同符號表示
$.ajax({
url: "https://egis.moea.gov.tw/MoeaEGFxData_WebAPI_Inside/InnoServe/BusinessBUSM?resptype=GeoJson&x=121.509&y=25.0401&buffer=1000",
type: 'GET',
success: function (data) {
var symbol = {
radius: 3,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.8
};
L.geoJSON(data, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, symbol);
}
}).addTo(map);
}
});
完整程式碼
client side(map.html):
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
<script src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
<div id='map_div' style="height:100%"></div>
<script>
//利用leaflet初始化地圖
var map = L.map('map_div').setView([25.0375928,121.5529563], 10);
//加入內政部國土測繪中心wmts
var basemap=L.tileLayer('https://wmts.nlsc.gov.tw/wmts/EMAP/default/GoogleMapsCompatible/{z}/{y}/{x}', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
//從Server端API接口把POI展在地圖上,並binding一個popup
$.ajax({
url: "/api/Poi",
contentType: 'application/json',
type: 'GET',
contentType: 'application/json; charset=utf-8',
success: function(data) {
$.each(data.pois, function(k, v) {
L.marker([v[0], v[1]]).addTo(map)
.bindPopup(v.name)
.openPopup();
});
}
});
//介接經濟部商家查詢api
$.ajax({
url: "https://egis.moea.gov.tw/MoeaEGFxData_WebAPI_Inside/InnoServe/BusinessBUSM?resptype=GeoJson&x=121.509&y=25.0401&buffer=1000",
type: 'GET',
success: function (data) {
var symbol = {
radius: 3,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.8
};
L.geoJSON(data, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, symbol);
}
}).addTo(map);
}
});
</script>
server side(ApiController.cs):
API接口取資料庫中的據點資料,假設使用mongodb去Query到bson document..
//取資料接口..
[Route("api/Poi")]
[httpget]
public JsonResult Poi()
{
//Bson collection example [{"name":"市府店","geo":[25.0375,121.5529]},{"name":"西門店","geo":[25.0401,121.509]}....]
List<PoiDataModel> pois = List<PoiDataModel>();
//取資料...
略..
return Json(...)
}
//新增資料接口...
[Route("api/Poi")]
[httppost]
public JsonResult GetPois(PoiDataModel poi)
{
//新增資料進資料庫...
略..
}
上面範例,結果如下: